package com.ben.multiple.util;

import lombok.extern.slf4j.Slf4j;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.TimeZone;

/**
 * @author eversec
 */
@Slf4j
public final class DateUtils {
    private DateUtils() {
    }

    public static final String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    public static final String PURE_DATE_TIME_PATTERN = "yyyyMMddHHmmss";
    public static final String DATE_PATTERN = "yyyy-MM-dd";
    public static final String PURE_DATE_PATTERN = "yyyyMMdd";
    public static final String TIME_PATTERN = "HH:mm:ss";
    public static final String PURE_TIME_PATTERN = "HHmmss";
    public static final String PURE_DATE_TIME_MILLI_PATTERN = "yyyyMMddHHmmssSSS";

    public static final ZoneId CHINA_ZONE_ID = ZoneId.of("Asia/Shanghai");
    public static final ZoneOffset CHINA_ZONE_OFFSET = ZoneOffset.ofHours(8);
    public static final TimeZone CHINA_TIME_ZONE = TimeZone.getTimeZone(CHINA_ZONE_ID);

    public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern(DATE_TIME_PATTERN);
    public static final DateTimeFormatter PURE_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern(PURE_DATE_TIME_PATTERN);
    public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern(DATE_PATTERN);
    public static final DateTimeFormatter PURE_DATE_FORMATTER = DateTimeFormatter.ofPattern(PURE_DATE_PATTERN);
    public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern(TIME_PATTERN);
    public static final DateTimeFormatter PURE_TIME_FORMATTER = DateTimeFormatter.ofPattern(PURE_TIME_PATTERN);
    public static final DateTimeFormatter PURE_DATE_TIME_MILLI_FORMATTER = DateTimeFormatter.ofPattern(PURE_DATE_TIME_MILLI_PATTERN);

    public static Date parseToDate(String timeStr, String format) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        Date result = null;
        try {
            result = simpleDateFormat.parse(timeStr);
        } catch (Exception e) {
            log.error("parseToDate fail, timeStr : {}, format : {}", timeStr, format, e);
        }
        return result;
    }

    public static String formatDate(Date date, String format) {
        try {
            return new SimpleDateFormat(format).format(date);
        } catch (Exception e) {
            log.error("formatDate fail, date : {}, format : {}", date, format, e);
        }
        return null;
    }

    public static Date localDateTimeToDate(LocalDateTime time) {
        if (time == null) {
            return null;
        }
        return Date.from(time.toInstant(CHINA_ZONE_OFFSET));
    }

    public static LocalDateTime dateToLocalDateTime(Date date) {
        if (date == null) {
            return null;
        }
        return LocalDateTime.ofInstant(date.toInstant(), CHINA_ZONE_ID);
    }

    public static LocalDateTime parseToLocalDateTime(String timeStr) {
        if (timeStr == null) {
            log.warn("parseToLocalDateTime fail, timeStr is null");
            return null;
        }
        String pureTime = timeStr.trim().replace("-", "")
                .replace("/", "")
                .replace(" ", "")
                .replace("T", "")
                .replace(":", "")
                .replace("年", "")
                .replace("月", "")
                .replace("日", "")
                .replace("时", "")
                .replace("分", "")
                .replace("秒", "");
        int index = pureTime.indexOf(".");
        if (index > -1) {
            pureTime = pureTime.substring(0, index);
        }
        try {
            return LocalDateTime.parse(pureTime, PURE_DATE_TIME_FORMATTER);
        } catch (Exception e) {
            log.error("parseToLocalDateTime fail, timeStr : {}", timeStr, e);
            return null;
        }
    }

    public static LocalDate parseToLocalDate(String dateStr) {
        if (dateStr == null) {
            log.warn("parseToLocalDate fail, dateStr is null");
            return null;
        }
        String pureTime = dateStr.replace("-", "")
                .replace("/", "")
                .replace(" ", "")
                .replace("T", "")
                .replace(":", "")
                .replace("年", "")
                .replace("月", "")
                .replace("日", "")
                .replace("时", "")
                .replace("分", "")
                .replace("秒", "");
        int index = pureTime.indexOf(".");
        if (index > -1) {
            pureTime = pureTime.substring(0, index);
        }
        int length = pureTime.length();
        if (length < 8) {
            log.warn("parseToLocalDate, param error, dateStr : {}", dateStr);
            return null;
        }
        if (length > 8) {
            pureTime = pureTime.substring(0, 8);
        }
        try {
            return LocalDate.parse(pureTime, PURE_DATE_FORMATTER);
        } catch (Exception e) {
            log.error("parseToLocalDate fail, dateStr : {}", dateStr, e);
            return null;
        }
    }

    public static LocalDateTime parseToLocalDateTimeForObj(Object time) {
        if (time == null) {
            log.warn("parseToLocalDateTimeForObj, time is null");
            return null;
        }
        if (time instanceof LocalDateTime) {
            return (LocalDateTime) time;
        }
        if (time instanceof Date) {
            return LocalDateTime.ofInstant(((Date) time).toInstant(), CHINA_ZONE_ID);
        }
        String timeStr = String.valueOf(time).trim();
        return parseToLocalDateTime(timeStr);
    }

    public static Date parseToDateForObj(Object time) {
        if (time == null) {
            log.warn("parseToDateForObj, time is null");
            return null;
        }
        if (time instanceof Date) {
            return (Date) time;
        }
        if (time instanceof LocalDateTime) {
            return Date.from(((LocalDateTime) time).toInstant(CHINA_ZONE_OFFSET));
        }
        String timeStr = String.valueOf(time).trim();
        LocalDateTime localDateTime = parseToLocalDateTime(timeStr);
        if (localDateTime == null) {
            log.warn("parseToDateForObj, localDateTime is null");
            return null;
        }
        return Date.from(localDateTime.toInstant(CHINA_ZONE_OFFSET));
    }

}
